package grammer.phrase;

import grammer.DirectObject;
import grammer.LocalObject;
import grammer.ModalObject;
import grammer.Predicate;
import grammer.Subject;
import grammer.Type1TimeObject;
import grammer.Type2TimeObject;
import grammer.components.ObjectEnum;
import grammer.components.PredicateEnum;

import java.util.Vector;

public class PhraseEvaluator {
	private Vector<PredicateEnum> class1Predicates, class2Predicates,
			class3Predicates, class4Predicates, class5Predicates,
			class7Predicates;
	private Vector<ObjectEnum> class5Objects, class4Objects, class31Objects,
			class32Objects;

	public PhraseEvaluator() {
		class1Predicates = new Vector<PredicateEnum>();
		class2Predicates = new Vector<PredicateEnum>();
		class3Predicates = new Vector<PredicateEnum>();
		class4Predicates = new Vector<PredicateEnum>();
		class5Predicates = new Vector<PredicateEnum>();
		class7Predicates = new Vector<PredicateEnum>();
		class31Objects = new Vector<ObjectEnum>();
		class32Objects = new Vector<ObjectEnum>();
		class5Objects = new Vector<ObjectEnum>();
		class4Objects = new Vector<ObjectEnum>();
		class5Objects = new Vector<ObjectEnum>();

		initPredicates();

	}

	public int eval(Phrase p) {
		System.out.println(p);
		if (p.isWeather()) {
			if (p.getCount() == 2)
				if (p.get(1) instanceof Type1TimeObject)
					return 10;
				else {
					System.out.println("Invalid suffix to weather command");
				}
			else {
				System.out
						.println("Invalid number of Tokens for weatherCommand");
			}
		} else {
			int pClass = getPredicateClass(p);
			boolean result = invokeClass(pClass, p);
			if (result == true)
				return pClass;
		}
		return (-1);
	}

	private int getPredicateClass(Phrase p) {
		if (p.get(1) instanceof Predicate) {
			PredicateEnum pEn = ((Predicate) p.get(1)).getPredicate();
			if (class1Predicates.contains(pEn))
				return 1;
			if (class2Predicates.contains(pEn))
				return 2;
			if (class3Predicates.contains(pEn))
				return 3;
			if (class4Predicates.contains(pEn))
				return 4;
			if (class5Predicates.contains(pEn))
				return 5;
			if (class7Predicates.contains(pEn))
				return 7;
		}
		return (-1);
	}

	private void initClass1() {
		class1Predicates.add(PredicateEnum.COMES_HOME);
		class1Predicates.add(PredicateEnum.LEAVES);
		class1Predicates.add(PredicateEnum.OPENS_WINDOW);
		class1Predicates.add(PredicateEnum.CLOSES_WINDOW);
		class1Predicates.add(PredicateEnum.GOES_TO_BED);
		class1Predicates.add(PredicateEnum.DRINKS);
		class1Predicates.add(PredicateEnum.TURNS_EVERYTHING_OFF);
	}

	private void initClass2() {
		class2Predicates.add(PredicateEnum.EATS);
		class2Predicates.add(PredicateEnum.IS_RESTING);
		class2Predicates.add(PredicateEnum.SHOWERS);
	}

	private void initClass3() {
		class3Predicates.add(PredicateEnum.WASHES);

		class31Objects.add(ObjectEnum.SINK);
		class31Objects.add(ObjectEnum.BATHTUB);
		class31Objects.add(ObjectEnum.CLOTHES);
		class31Objects.add(ObjectEnum.HIMSELF);
		class31Objects.add(ObjectEnum.HERSELF);
		class31Objects.add(ObjectEnum.SHOWER);

		class3Predicates.add(PredicateEnum.USES);
		class32Objects.add(ObjectEnum.TOILET);
		class32Objects.add(ObjectEnum.REFRIGERATOR);
		class32Objects.add(ObjectEnum.COMPUTER);
		class32Objects.add(ObjectEnum.SINK);
		class32Objects.add(ObjectEnum.GAS_COOKER);
		class32Objects.add(ObjectEnum.VACUUM_CLEANER);

	}

	private void initClass4() {
		class4Predicates.add(PredicateEnum.TURNS_ON);
		class4Predicates.add(PredicateEnum.TURNS_OFF);
		class4Objects.add(ObjectEnum.TELEVISION);
		class4Objects.add(ObjectEnum.AIR_CONDITIONING);
		class4Objects.add(ObjectEnum.COMPUTER);
		class4Objects.add(ObjectEnum.LIGHT);
		class4Objects.add(ObjectEnum.STOVE);
		class4Objects.add(ObjectEnum.ELECTRIC_PLATE);
		class4Objects.add(ObjectEnum.COFFEE_FILTER);
		class4Objects.add(ObjectEnum.TOASTER);
		class4Objects.add(ObjectEnum.WASHING_MACHINE);
		class4Objects.add(ObjectEnum.RADIATOR);
		class4Objects.add(ObjectEnum.HEATING);

	}

	private void initClass5() {
		class5Predicates.add(PredicateEnum.SETS);
		class5Objects.add(ObjectEnum.AIR_CONDITIONING);
		class5Objects.add(ObjectEnum.REFRIGERATOR);
		class5Objects.add(ObjectEnum.STOVE);
		class5Objects.add(ObjectEnum.RADIATOR);
		class5Objects.add(ObjectEnum.HEATING);

	}

	private void initClass7() {
		class7Predicates.add(PredicateEnum.ENTERS);
		class7Predicates.add(PredicateEnum.WAKES_UP_IN);
	}

	private void initPredicates() {
		initClass1();
		initClass2();
		initClass3();
		initClass4();
		initClass5();
		initClass7();

	}

	private boolean invokeClass(int i, Phrase p) {
		boolean result = false;
		switch (i) {
		case 1:
			result = isClass1(p);
			break;
		case 2:
			result = isClass2(p);
			break;
		case 3:
			result = isClass3(p);
			break;
		case 4:
			result = isClass4(p);
			break;
		case 5:
			result = isClass5(p);
			break;
		case 7:
			result = isClass7(p);
			break;
		default:
			result = false;
			break;
		}
		System.out.println("EVALUATING...");
		System.out.println(p);
		System.out.println("evaluated to :" + result + " type: " + i);
		return result;
	}

	private boolean isClass1(Phrase p) {
		if (p.getCount() == 3)
			if (p.get(0) instanceof Subject)
				if (p.get(2) instanceof Type1TimeObject)
					return true;
				else {
					System.out.println("Invalid time for predicate: "
							+ ((Predicate) p.get(1)).getPredicate().toString());
				}
			else {
				System.out.println("No subject");
			}
		else {
			System.out.println("Invalid number of Tokens for predicate: "
					+ ((Predicate) p.get(1)).getPredicate().toString());
		}
		return false;
	}

	private boolean isClass2(Phrase p) {
		if (p.getCount() == 3)
			if (p.get(0) instanceof Subject)
				if (p.get(2) instanceof Type2TimeObject)
					return true;
				else {
					System.out.println("Invalid time for predicate: "
							+ ((Predicate) p.get(1)).getPredicate().toString());
				}
			else {
				System.out.println("No subject");
			}
		else {
			System.out.println("Invalid number of Tokens for predicate: "
					+ ((Predicate) p.get(1)).getPredicate().toString());
		}
		return false;
	}

	// verify object
	private boolean isClass3(Phrase p) {
		if (p.getCount() == 4)
			if (p.get(0) instanceof Subject)
				if (p.get(2) instanceof DirectObject)
					if (p.get(3) instanceof Type2TimeObject) {
						if (p.get(1).getMember().equals(PredicateEnum.WASHES)) {
							if (class31Objects.contains(p.get(2).getMember()))
								return true;
						}
						if (p.get(1).getMember().equals(PredicateEnum.USES)) {
							if (class32Objects.contains(p.get(2).getMember()))
								return true;
						}
					} else {
						System.out.println("Invalid time for predicate: "
								+ ((Predicate) p.get(1)).getPredicate()
										.toString());
					}
				else {
					System.out.println("No direct object for predicate: "
							+ ((Predicate) p.get(1)).getPredicate().toString());
				}
			else {
				System.out.println("No subject");
			}
		else {
			System.out.println("Invalid number of Tokens for predicate: "
					+ ((Predicate) p.get(1)).getPredicate().toString());
		}
		return false;
	}

	private boolean isClass4(Phrase p) {
		if (p.getCount() == 4)
			if (p.get(0) instanceof Subject)
				if (p.get(2) instanceof DirectObject
						&& class4Objects.contains(p.get(2).getMember()))
					if (p.get(3) instanceof Type1TimeObject)
						return true;
					else {
						System.out.println("Invalid time for predicate: "
								+ ((Predicate) p.get(1)).getPredicate()
										.toString());
					}
				else {
					System.out.println("No direct object for predicate: "
							+ ((Predicate) p.get(1)).getPredicate().toString());
				}
			else {
				System.out.println("No subject");
			}
		else {
			System.out.println("Invalid number of Tokens for predicate: "
					+ ((Predicate) p.get(1)).getPredicate().toString());
		}
		return false;
	}

	private boolean isClass5(Phrase p) {
		if (p.getCount() == 5)
			if (p.get(0) instanceof Subject)
				if (p.get(2) instanceof DirectObject
						&& class5Objects.contains(p.get(2).getMember()))
					if (p.get(3) instanceof ModalObject)
						if (p.get(4) instanceof Type1TimeObject)
							return true;
						else {
							System.out.println("Invalid time for predicate: "
									+ ((Predicate) p.get(1)).getPredicate()
											.toString());
						}
					else {
						System.out.println("No modal object for predicate: "
								+ ((Predicate) p.get(1)).getPredicate()
										.toString());
					}
				else {
					System.out.println("No direct object");
				}
			else {
				System.out.println("No subject");
			}
		else {
			System.out.println("Invalid number of Tokens for predicate: "
					+ ((Predicate) p.get(1)).getPredicate().toString());
		}
		return false;
	}

	private boolean isClass7(Phrase p) {
		if (p.getCount() == 4)
			if (p.get(0) instanceof Subject)
				if (p.get(2) instanceof LocalObject)
					if (p.get(3) instanceof Type1TimeObject)
						return true;
					else {
						System.out.println("Invalid time for predicate: "
								+ ((Predicate) p.get(1)).getPredicate()
										.toString());
					}
				else {
					System.out.println("No local object for predicate: "
							+ ((Predicate) p.get(1)).getPredicate().toString());
				}
			else {
				System.out.println("No subject");
			}
		else {
			System.out.println("Invalid number of Tokens for predicate: "
					+ ((Predicate) p.get(1)).getPredicate().toString());
		}
		return false;
	}

}
